import logging
from executer.invoker import  Invoker
import protocol
import os

LOCAL_SVN_PATH = 'task/script'

class Manager():
    def __init__(self, uploadcfg, protocolhandler, svn):
        self.task_list = {}
        self.protocolhandler = protocolhandler
        self.protocolhandler.RegisterProtocol(protocol.s2c_start_task, self.OnStartTask)
        self.protocolhandler.RegisterProtocol(protocol.s2c_terminated_task, self.OnTerminatedTaskRequest)
        self.uploadcfg = uploadcfg 
        self.svn = svn
    
    def AddTask(self, templateid, taskid, subid, runtype, info, args):
        if taskid in self.task_list:
            raise ValueError(''.format('{0} has aleady exits', info))
        if runtype == 'script':
            self.svn.Update()
            scriptpath = os.path.join(LOCAL_SVN_PATH, info['scriptname'])
            if not os.path.exists(scriptpath):
                raise ValueError('not exits script %s' % info['scriptname'])
        self.task_list[taskid] = Invoker(self.uploadcfg, templateid, taskid, subid, runtype, info, args)
        self.task_list[taskid].Start()
    
    def StopTask(self, taskid):
        if taskid not in self.task_list:
            raise ValueError(''.format('{0} not in tasklist', taskid))
        
        task  = self.task_list[taskid]
        task.Stop()
        
        self.task_list.pop(taskid)
    
    def GetTaskStatus(self, taskid):
        if taskid not in self.task_list:
            raise ValueError(''.format('{0} not in tasklist', taskid))
        return self.task_list[taskid].Status()
    
    def StopAll(self):
        for v in self.task_list.values():
            v.Stop()
        
        self.task_list.clear()
    
    def Loop(self):
        finishtask = []
        for k, v in self.task_list.items():
            if v.Finished() == True:
                finishtask.append(k)
                self.DoTaskFinish(v)
        for  v in finishtask:
            self.task_list.pop(v)
            
    def OnStartTask(self, request):
        try:
            self.AddTask(request.templateid, request.taskid, request.subid,
                         request.type, request.info, request.args)
        except Exception as e:
            logging.exception(e)
            self.DoStartTaskRespond(request.taskid, request.subid, False, str(e))
        else:
            self.DoStartTaskRespond(request.taskid, request.subid, True, None)
    
    def DoStartTaskRespond(self, id, subid, result, message = ''):
        respond = protocol.C2SStartTaskRespond()
        respond.taskid = id
        respond.subid = subid
        respond.result = result
        respond.message = message
        self.protocolhandler.DoSend(respond)
    
    def DoTaskFinish(self, task):
        logging.info(task.result)
        respond = protocol.C2STaskFinish()
        respond.result = task.result
        respond.taskid = task.taskid
        respond.subid = task.subid
        respond.message = task.resultmessage
        respond.addtional_mail_receiver = task.addtional_mail_receiver
        self.protocolhandler.DoSend(respond)
        
    def OnTerminatedTaskRequest(self, request):
        respond = protocol.C2STerminatedTaskRespond()
        if request.taskid not in self.task_list:
            logging.warn('terminated not exit')
            respond.message = 'terminated not exit'
            respond.result = False
            self.protocolhandler.DoSend(respond)
            return
        
        task  = self.task_list[request.taskid]
        if task.subid != request.subid:
            logging.warn('terminated subid not match')
            respond.message = 'terminated subid not match'
            respond.result = False
            self.protocolhandler.DoSend(respond)
            return
        task.Stop()
        respond.result = True
        respond.taskid = request.taskid 
        respond.subid = task.subid
        self.task_list.pop(request.taskid)
        self.protocolhandler.DoSend(respond)
        
        
    def HasTask(self, taskid):
        return taskid in self.task_list
    
        
        